package ru.amse.tsyganov.jumleditor.commands;

import java.util.ArrayList;
import java.util.LinkedList;

public class ViewsManager {
	private final int maxSize;
	
	private final LinkedList<Command> executedCommands =
		new LinkedList<Command>();
	
	private final LinkedList<Command> cancelledCommands = 
		new LinkedList<Command>();
	
	private final ArrayList<CommandActionListener> listeners = 
		new ArrayList<CommandActionListener>();
	
	public ViewsManager() {
		maxSize = Integer.MAX_VALUE;
	}
	
	public ViewsManager(int maxSize) {
		if (maxSize < 0) {
			throw new IllegalArgumentException();
		}
		this.maxSize = maxSize;
	}
	
	public void executeCommand(Command command) {
		if (command == null) {
			throw new IllegalArgumentException();
		}
		cancelledCommands.clear();
		if (executedCommands.size() == maxSize) {
			executedCommands.removeFirst();
		}
		executedCommands.addLast(command);
		command.execute();
		fire();
	}
	
	public boolean undo() {
		if (executedCommands.size() == 0) {
			return false;
		}
		
		Command lastCommand = executedCommands.removeLast();
		lastCommand.unexecute();
		cancelledCommands.addLast(lastCommand);
		fire();
		return true;
	}
	
	public boolean redo() {
		if (cancelledCommands.size() == 0) {
			return false;
		}
		
		Command cancelledCommand = cancelledCommands.removeLast();
		cancelledCommand.execute();
		executedCommands.addLast(cancelledCommand);
		fire();
		return true;
	}
	
	public void clear() {
		executedCommands.clear();
		cancelledCommands.clear();
		fire();
	}
	
	public boolean canUndo() {
		return executedCommands.size() != 0;
	}
	
	public boolean canRedo() {
		return cancelledCommands.size() != 0;
	}
	
	public void addListener(CommandActionListener listener) {
		listeners.add(listener);
	}
	
	private void fire() {
		for (CommandActionListener l : listeners) {
			l.action();
		}
	}
}
